package org.rednebula.framework.core.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.rednebula.framework.core.model.State;
import org.rednebula.framework.core.model.domain.IModel;
import org.springframework.stereotype.Service;



@Service("ModelAspect")
@Aspect
public class ModelAspect {
	
	@Pointcut("target(org.rednebula.framework.core.model.domain.IModel)")
	private void common(){}
	
	@Pointcut("execution( * *.set*(**))")
	private void setPointCut(){}
	
	@Pointcut("common() && setPointCut()")
	private void setCombinePointCut(){}
	
	@After(value="setCombinePointCut()")
	public void weaveSetMethod(JoinPoint join){
		weaveSetMethodInternal(join);
	}
	
	private void weaveSetMethodInternal(JoinPoint join){
		Object target=join.getTarget();
		if(target instanceof  IModel ){
			IModel self=(IModel)target;
			IModel parent=self.getParent();
			self.changeState(State.MODIFY);
			if(parent!=null)
				parent.changeChildrenState(self.getClass(), State.MODIFY);
		}
	}
	
	private void savePointCut(){}
	
	@Pointcut("execution( * *.create(org.rednebula.framework.core.IEnvironment))")
	private void createPointCut(){}
	
	@Pointcut("common() && createPointCut()")
	private void combineCreatePointCut(){
	}
	@After(value="combineCreatePointCut()")
	public void weaveCreatePointCut(JoinPoint join){
		weaveCreatePointCutInternal(join);
	}
	
	private void weaveCreatePointCutInternal(JoinPoint join){
		Object target=join.getTarget();
		if(target instanceof  IModel ){
			IModel self=(IModel)target;
			IModel parent=self.getParent();
			self.changeState(State.NORMAL);
			if(parent!=null)
				parent.changeChildrenState(self.getClass(), State.NORMAL);
		}
	}
	
	@Pointcut("execution( * *.load(org.rednebula.framework.core.IEnvironment))")
	private void loadPointCut(){}
	
	@Pointcut("common() && loadPointCut()")
	private void combineLoadPointCut(){
	}
	
	@After(value="combineLoadPointCut()")
	public void weaveLoadPointCut(JoinPoint join){
		weaveLoadPointCutInternal(join);
	}
	
	private void weaveLoadPointCutInternal(JoinPoint join){
		Object target=join.getTarget();
		if(target instanceof  IModel ){
			IModel self=(IModel)target;
			IModel parent=self.getParent();
			self.changeState(State.NORMAL);
			if(parent!=null)
				parent.changeChildrenState(self.getClass(), State.NORMAL);
		}
	}
	
	@Pointcut("execution( * *.delete(org.rednebula.framework.core.IEnvironment))")
	private void deletePointCut(){}
	
	@Pointcut("common() && deletePointCut()")
	private void combineDeletePointCut(){
	}
	
	@After(value="combineDeletePointCut()")
	public void weaveDeletePointCut(JoinPoint join){
		weaveDeletePointCutInternal(join);
	}
	
	private void weaveDeletePointCutInternal(JoinPoint join){
		Object target=join.getTarget();
		if(target instanceof  IModel ){
			IModel self=(IModel)target;
			IModel parent=self.getParent();
			self.changeState(State.DELETE);
			if(parent!=null)
				parent.changeChildrenState(self.getClass(), State.NORMAL);
		}
	}
	
	@Pointcut("execution( * *.modify(org.rednebula.framework.core.IEnvironment))")
	private void modifyPointCut(){}
	
	@Pointcut("common() && modifyPointCut()")
	private void combineModifyPointCut(){
	}
	
	@After(value="combineModifyPointCut()")
	public void weaveModifyPointCut(JoinPoint join){
		weaveModifyPointCutInternal(join);
	}
	
	private void weaveModifyPointCutInternal(JoinPoint join){
		Object target=join.getTarget();
		if(target instanceof  IModel ){
			IModel self=(IModel)target;
			IModel parent=self.getParent();
			self.changeState(State.NORMAL);
			if(parent!=null)
				parent.changeChildrenState(self.getClass(), State.NORMAL);
		}
	}
    
}
